package cn.net.springboot.netty.http_demo;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.kqueue.KQueueEventLoopGroup;
import io.netty.channel.kqueue.KQueueServerSocketChannel;
import io.netty.channel.kqueue.KQueueSocketChannel;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpRequestDecoder;
import io.netty.handler.codec.http.HttpResponseEncoder;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpVersion;

/**
 * @author Chris
 * @version 1.0.0
 * @date 2019/05/15
 * @since 1.0.0
 */
public class HttpServerWithKqueue {
    public static void openServer(int port) {
        ServerBootstrap bootstrap = new ServerBootstrap();

        bootstrap.channel(KQueueServerSocketChannel.class);

        // epoll only supported on mac
        EventLoopGroup boss = new KQueueEventLoopGroup(1);
        EventLoopGroup work = new KQueueEventLoopGroup(8);

        bootstrap.group(boss, work);

        bootstrap.childHandler(new ChannelInitializer<KQueueSocketChannel>() {
            @Override
            protected void initChannel(KQueueSocketChannel ch) throws Exception {
                // http request 报文解码
                ch.pipeline().addLast("http-decoder", new HttpRequestDecoder());
                // 请求聚合
                ch.pipeline().addLast("http", new HttpObjectAggregator(65536));
                // http response 报文编码
                ch.pipeline().addLast("http-response-encode", new HttpResponseEncoder());
                // 业务处理
                ch.pipeline().addLast("http-servlet", new HttpServletHandler());
            }
        });

        try {
            ChannelFuture future = bootstrap.bind(port).sync();
            System.out.println("服务已启动：" + port);
            future.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            boss.shutdownGracefully();
            work.shutdownGracefully();
        }

    }

    private static class HttpServletHandler extends SimpleChannelInboundHandler {
        @Override
        protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
            // 业务处理
            FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
            response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/html;charset=UTF-8");
            response.content().writeBytes("hello luban is a good man".getBytes());

            ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
        }
    }

    public static void main(String[] args) {
        HttpServerWithKqueue.openServer(9088);
    }

}
